Шаг 7 - Обработка команд меню

Загрузить проект

Создание проекта

Мучаем дальше наш проект. Если Вы захотите перенести файлы из предыдущего проекта, то учтите, что нужно будет перенести еще и resource.h и step6.rc. Эти файлы нужно добавить в проект, перед добавлением step6.rc нужно переименовать в step7.rc.

К моменту начала ваш проект должен иметь меню, и пункт меню Exit должен быть серым. Есть песня со словами "был бы серым, но кто-то взял и покрыл меня сажей". Или в этом роде, не в этом суть, суть в процессе. Меню серое, а пока оно серое, стучи не стучи толку нет. Вот мы и будем делать его черным.

7_1.gif (2098 b)

Создаем код

Добавляем функцию к классу рамки окна для обработки команд меню. Эта функция будет использоваться в обработчике событий. Она должна быть типа void и без параметров.

class CMainWnd : public CFrameWnd
{
public:
        CMainWnd();     // Конструктор по умолчанию
        afx_msg void OnLButtonDblClk( UINT, CPoint );   // виртуальная процедура ответа на левую кнопку
        afx_msg void OnRButtonDblClk( UINT, CPoint );   // виртуальная процедура ответа на правую кнопку
        afx_msg void OnKeyDown( UINT, UINT, UINT );     // виртуальная процедура ответа на клавишу
        int OnCreate(LPCREATESTRUCT lpCreateStruct);    // эта функция вызывается при создании окна
        void MenuExit();        // Процедура реакции на выбор пункта меню 
        ~CMainWnd();    // Деструктор
private:
        CStatic* MyStatic;      // Указатель на объект надпись
        CMyButton* MyButton;    // Элемент управления кнопка
        CEdit* MyEdit;  // Указатель на объект поле редактирования
        CStatusBar m_wndStatusBar;      // класс панели состояния
        CMenu m_wndMenu;        // Это наш класс Меню
        DECLARE_MESSAGE_MAP();  // таблица откликов
};

А теперь в обработчике событий нужно добавить реакцию на выбор пункта меню:

BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)  // таблица откликов на сообщения
        ON_WM_LBUTTONDBLCLK()   // реакция на нажатие левой кнопки мыши
        ON_WM_RBUTTONDBLCLK()   // реакция на нажатие правой кнопки мышки
        ON_WM_KEYDOWN() // реакция на нажатие клавиши
        ON_WM_CREATE()  // событие создания окна
        ON_COMMAND(ID_FILE_EXIT,MenuExit)    // Вот она , обработка реакции на выбор меню
END_MESSAGE_MAP()

Обратите внимание на идентификатор пункта меню. Откуда я его взял? При создании пункта меню ему задается идентификатор, который записывается в resource.h.

// Used by step7.rc
//
#define IDR_MENU                        101
#define ID_FILE_EXIT                    40001

// Next default values for new objects

При желании его можно поменять в режиме редактирования ресурсов, щелкнув правой кнопкой мыши по пункту меню и вызвав свойства (Properties).

7_2.gif (2569 b)

И сама функция обработки (вообще это процедура, так как не возвращает значение, но, вроде, в С++ всё функции?). Её можно поместить сразу после обработки сообщений.

void CMainWnd::MenuExit()
{
        DestroyWindow(); // Уничтожить окно
}

Собирите проект и запустите программу. Пункт меню будет черный. Это говорит о том, что его можно использовать. При выборе этого пункта меню программа прекратит свою работу.

7_3.gif (1989 b)

Описание

В классе необходимо описать функцию реакции. Просмотрите предыдущие обработки. Не перепутайте. Объявляйте функцию в классе, в котором ее и будут обрабатывать, и в котором есть обработчик.

Макрос ON_COMMAND предназначен для обработки команд вашего меню. В параметры ставите идентификатор и имя функции. Функция должна иметь тип void, что значит пусто, и она не вернет параметры. После Паскаля это удивительно. Что это за функция, которая не возвращает параметры. Это процедура!! Ну, это на совести С++. То, что она тип void, логично: куда возвращать результат, в меню что ли? И без параметров она, откуда им взяться? Правило: функция реакции на меню с виду пустая, как бубен.

Функция DestroyWindow() разрушает окно. При этом тип у неё BOOL, окно и не всегда можно уничтожить, помните это и обрабатывайте, если необходимо. Правило: внутри пустой функции важно содержание!

Программа реагирует на нажатие меню, как я на запах кофе!

Шпаргалка

  1. Добавляем функцию, которая обработает вызов меню, в класс рамки окна:
    class CMainWnd : public CFrameWnd
    {
    public:
            ......
            void MenuExit();
            ......
    };
    
  2. Создаем её обработку в обработчике событий класса рамки окна.
    BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
            ......
            ON_COMMAND(ID_FILE_EXIT,MenuExit)
            ......
    END_MESSAGE_MAP()
    
  3. Пишем, что делать:
    void CMainWnd::MenuExit()
    {
            ......
    }
    
Hosted by uCoz